﻿using System;
using System.Linq;
using System.Threading.Tasks;
using System.Transactions;
using Elsa.Services.Models;
using HengTong.Model;
using HengTong.Model.Db;
using HengTong.Model.Db.Hr;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using TiaoTaoHelper.Wtm.Interfaces;
using TiaoTaoHelper.Wtm.Models;
using TiaoTaoHelper.Wtm.Workflow;
using WalkingTec.Mvvm.Core;
using WalkingTec.Mvvm.Core.WorkFlow;

namespace HengTong.ViewModel.Hr.SysHrInterviewRequestBillVms;

public partial class SysHrInterviewRequestBillVm
{
    // 面试申请流程结束后，把数据增加到录用候选池中
    [WorkflowOperation("添加到录用候选池", "将面试数据添加到录用候选池", "面试申请")]
    public async Task AddToInterviewPool(ActivityExecutionContext context)
    {
        using var scope = Wtm.ServiceProvider.CreateScope();
        var logger = scope.ServiceProvider.GetRequiredService<ILogger<SysHrInterviewRequestBillVm>>();

        string currentUser = "workflow";
        if (context.Input is WtmApproveInput input)
        {
            currentUser = input.CurrentUser?.ITCode ?? "workflow";
        }

        if (Entity == null || Entity.ID == Guid.Empty)
        {
            MSD.AddModelError(" ", "单据数据不存在");
            return;
        }

        using var transactionScope = new TransactionScope(
            TransactionScopeOption.Required,
            new TransactionOptions
            {
                IsolationLevel = IsolationLevel.ReadCommitted,
                Timeout = TimeSpan.FromMinutes(5)
            },
            TransactionScopeAsyncFlowOption.Enabled);

        try
        {
            var billNo = await GenerateBillNo("LY");
            var newStaffNo = await GenerateHiredStaffNoAsync();

            var pool = new SysHrInterviewPool
            {
                BillNo = billNo,
                HiredStaffNo = newStaffNo,
                InterviewRequestBillId = Entity.ID,
                HrStatus = HrStatus.已审核,
                CreateBy = Entity.CreateBy ?? Wtm.LoginUserInfo?.ITCode,
                CreateTime = DateTime.Now
            };

            await DC.Set<SysHrInterviewPool>().AddAsync(pool);
            logger.LogInformation("已将面试申请ID {BillId} 添加到录用候选池", Entity.ID);

            Entity.WorkflowStatus = WorkflowStatus.已完成;
            DC.UpdateProperty(Entity, x => x.WorkflowStatus);
            logger.LogInformation("单据编码 {BillCode} 状态更新为已完成", Entity.BillCode);

            await DC.SaveChangesAsync();
            transactionScope.Complete();
            logger.LogInformation("录用候选池插入完成，BillId: {BillId}", Entity.ID);
        }
        catch (Exception e)
        {
            logger.LogError(e, "处理面试申请ID {BillId} 时发生错误: {ErrorMessage}", Entity.ID, e.Message);
            MSD.AddModelError(" ", $"处理面试申请操作失败: {e.Message}");
            throw;
        }
    }

    private async Task<string> GenerateHiredStaffNoAsync()
    {
        // 检测外层是否已有事务（如 TransactionScope）
        var hasAmbient =
            System.Transactions.Transaction.Current != null ||
            DC.Database.CurrentTransaction != null;

        async Task<string> GenerateAsync()
        {
            // 查询所有正数工号（从 SysPerson 表）
            var existingPersonStaffNos = await DC.Set<SysPerson>()
                .Where(x => x.StaffNo != null && !x.StaffNo.StartsWith("-"))
                .Select(x => x.StaffNo!)
                .AsNoTracking()
                .ToListAsync();

            // 查询录用候选池中的工号
            var existingPoolStaffNos = await DC.Set<SysHrInterviewPool>()
                .Where(x => x.HiredStaffNo != null)
                .Select(x => x.HiredStaffNo!)
                .AsNoTracking()
                .ToListAsync();

            // 合并两个表中的工号
            var allStaffNos = existingPersonStaffNos.Concat(existingPoolStaffNos).Distinct().ToList();

            var existingNumbers = allStaffNos
                .Select(s => int.TryParse(s, out var n) ? n : (int?)null)
                .Where(n => n.HasValue)
                .Select(n => n!.Value)
                .ToList();

            var maxNumber = existingNumbers.Any() ? existingNumbers.Max() : 0;
            var candidate = (maxNumber + 1).ToString();

            // 简单冲突重试，最多 5 次
            for (var i = 0; i < 5; i++)
            {
                var existsInPerson = await DC.Set<SysPerson>().AnyAsync(x => x.StaffNo == candidate);
                var existsInPool = await DC.Set<SysHrInterviewPool>().AnyAsync(x => x.HiredStaffNo == candidate);

                if (!existsInPerson && !existsInPool) return candidate;
                candidate = (int.Parse(candidate) + 1).ToString();
            }

            throw new InvalidOperationException("无法生成唯一的工号，请稍后重试。");
        }

        if (hasAmbient)
        {
            // 在外层事务内执行，不再开启本地事务
            return await GenerateAsync();
        }

        await using var tx = await DC.Database.BeginTransactionAsync();
        try
        {
            var result = await GenerateAsync();
            await tx.CommitAsync();
            return result;
        }
        catch
        {
            await tx.RollbackAsync();
            throw;
        }
    }


    [WorkflowOperation("驳回", "将单据状态设置为草稿", "面试申请")]
    public async Task Reject(ActivityExecutionContext context)
    {
        Entity.BillStatus = BillStatus.草稿;
        if (Entity is IBasePoco poco)
        {
            poco.UpdateTime = DateTime.Now;
            DC.UpdateProperty(Entity, x => x.UpdateTime);
            if (context.Input is WtmApproveInput input)
            {
                poco.UpdateBy = input.CurrentUser?.ITCode ?? "workflow";
                DC.UpdateProperty(Entity, x => x.UpdateBy);
            }
        }

        DC.UpdateProperty(Entity, x => x.BillStatus);
        await DC.SaveChangesAsync();
    }

    [WorkflowOperation("取消", "将流程状态设置为取消", "面试申请")]
    public async Task Cancel(ActivityExecutionContext context)
    {
        if (Entity is IBasePoco poco)
        {
            poco.UpdateTime = DateTime.Now;
            DC.UpdateProperty(Entity, x => x.UpdateTime);
            if (context.Input is WtmApproveInput input)
            {
                poco.UpdateBy = input.CurrentUser?.ITCode ?? "workflow";
                DC.UpdateProperty(Entity, x => x.UpdateBy);
            }
        }

        if (Entity is IBill bill)
        {
            bill.WorkflowStatus = WorkflowStatus.已取消;
            DC.UpdateProperty(Entity, x => x.WorkflowStatus);
        }

        await DC.SaveChangesAsync();
    }

    // 添加生成编号的方法
    private async Task<string> GenerateBillNo(string prefix)
    {
        var dateStr = DateTime.Now.ToString("yyyyMMdd");

        // 查询当日最大流水号
        var maxBillNo = await DC.Set<SysHrInterviewPool>()
            .Where(x => x.BillNo.StartsWith(prefix + dateStr))
            .Select(x => x.BillNo)
            .ToListAsync();

        var maxSequence = 0;
        if (maxBillNo.Any())
        {
            maxSequence = maxBillNo
                .Select(x => int.TryParse(x.Substring(x.Length - 3), out int seq) ? seq : 0)
                .DefaultIfEmpty(0)
                .Max();
        }

        return $"{prefix}{dateStr}{(maxSequence + 1):D3}";
    }
}